Lua Integrated Query (LIQ) is a SilverBullet specific Lua extension. It adds a convenient query syntax to the language in a backwards compatible way. It does so by overloading Lua’s default function call + single argument syntax when using query
as the function call. As a result, Lua programs using LIQ are still syntactically valid Lua.
The syntax for LIQ is query[my query](my query)
. In regular Lua [my query](my query)
is just another way of writing "my query"
(it is an alternative string syntax). Function calls that only take a string argument can omit parentheses, therefore query[my query](my query)
is equivalent to query("my query")
.
However, in Space Lua it interpreted as an SQL (and LINQ)-inspired integrated query language.
General syntax:
query[
from <var> = <expression>
where <expression>
order by <expression>
limit <expression>, <expression>
select <expression>
](
from <var> = <expression>
where <expression>
order by <expression>
limit <expression>, <expression>
select <expression>
)
LIQ can operate on any Lua collection.
For instance, to sort a list of numbers in descending order: ${queryfrom n = {1, 2, 3} order by n desc}
However, in most cases you’ll use it in conjunction with API/index#index.tag(name). Here’s an example querying the 3 pages that were last modified:
${query from p = index.tag "page" order by p.lastModified desc select p.name limit 3}
Note that the query returns a regular Lua table, so it can be part of a bigger expression:
${some(query from p = index.tag "page" limit 0) or "Matched no pages"}
Here are the clauses that are currently supported:
The from
clause specifies the source of your data. There are two syntactic variants:
With explicit variable binding:
from v = <<expression>>
binding each item to the variable v
.
And the shorter:
from <<expression>>
implicitly binding each item to the variable _
as well as making all attributes directly available as variables.
Example without variable binding: ${queryfrom {1, 2, 3} select _}
With variable binding: ${queryfrom n = {1, 2, 3} select n}
A more realistic example using index.tag
:
${queryfrom index.tag "page" order by lastModified select name limit 3}
The where
clause allows you to filter data. When the expression evaluated to a truthy value, the item is included in the result.
Example:
${queryfrom {1, 2, 3, 4, 5} where _ > 2}
Or to select all pages tagged with #meta
:
${queryfrom index.tag "page" where table.includes(tags, "meta"))}
Or select based on name (including folder) and a API/string|string function
${queryfrom index.tag "page" where name:startsWith("Person"))}
The order by
clause allows you to sort data, when desc
is specified it reverts the sort order.
As an example, the last 3 modified pages: ${query from index.tag "page" order by lastModified desc select name limit 3}
Sorting of strings can be adjusted with queryCollation
in ^Library/Std/Config
The limit
clause allows you to limit the number of results, optionally with an offset.
Example:
${queryfrom {1, 2, 3, 4, 5} limit 3}
You can also specify an offset to skip some results:
${queryfrom {1, 2, 3, 4, 5} limit 3, 2}
The select
clause allows you to transform each item in the result set. If omitted, it defaults to returning the item itself.
Some examples:
Double each number: ${queryfrom {1, 2, 3} select _ * 2}
Extract just the name from pages: ${queryfrom index.tag "page" select _.name limit 3}
You can also return tables or other complex values: ${query from p = index.tag "page" select { name = p.name, modified = p.lastModified } limit 3}
To render the output as a template, you can rely on the fact that queries return Lua tables. For example, to apply a template to render every page as a link:
${template.each(query from index.tag "page" order by lastModified desc limit 3, templates.pageItem)}
To render pages as links with their full local URL, use templates.fullPageItem
. For more information on available templates, see API/templates.